package com.polaris.live.ui.party.widget.videoseat.base

import android.content.Context
import android.util.AttributeSet
import android.view.TextureView
import android.widget.FrameLayout
import androidx.lifecycle.LifecycleOwner
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.im.sfs.bean.live.LiveRoomInfo
import com.polaris.live.im.sfs.bean.live.SendLiveMessage
import com.polaris.live.im.sfs.bean.live.payload.PartyEmojiPayloadBean
import com.polaris.live.ui.party.PartyUserStateUtil
import com.polaris.live.ui.party.widget.seat.party_seat.SeatItemView
import com.polaris.live.ui.party.widget.videoseat.PartyVideoStreamProxy
import com.polaris.live.ui.party.widget.videoseat.VideoSeatItemView
import com.polaris.live.ui.party.widget.videoseat.bean.VideoSeatBean
import com.polaris.live.ui.party.widget.videoseat.listener.PartyVideoSeatListener
import com.polaris.live.ui.party.widget.videoseat.listener.VideoStreamManageListener

/**
 *
 * @author Created by 天晴 on 2024/6/22 10:03
 * @since 1.0.0
 **/
abstract class BaseVideoSeatView<T : VideoSeatItemView>(context: Context, attrs: AttributeSet?) :
    FrameLayout(context, attrs) {

    private var mPartyVideoSeatListener: PartyVideoSeatListener? = null
    private val mViews = mutableListOf<T>()
    private var mIsInit: Boolean = false //是否初始化
    private var meSeat: T? = null //自己的座位信息
    private var mIsOnPause = false //是否是onPause状态
    private var mLastOnSeatState: Boolean = false //上次是否在座
    private var mLastSiteMicStatus: Int? = null //在座位上得语音开关状态
    private var mLastSiteVideoStatus: Int? = null //在座位上得视频开关状态

    /**
     * 视频位流管理
     */
    private val mPartyVideoStreamProxy by lazy {
        PartyVideoStreamProxy()
    }

    fun observe(owner: LifecycleOwner) {
        mPartyVideoStreamProxy.observe(owner)
    }

    /**
     * 座位数量
     */
    abstract fun getSeatCount(): Int

    abstract fun createView(seatId: Int): T

    /**
     * 初始化
     */
    fun initView() {
        for (seatId in 0 until getSeatCount()) {
            createView(seatId).apply {
                initView(seatId)
                mViews.add(this)
                setOnSingleClickListener {
                    if (mIsInit) {
                        mPartyVideoSeatListener?.clickItem(seatId, getData())
                    }
                }
            }
        }
    }

    /**
     * 根据userId查找座位上是否有这个人
     */
    fun getSeatBeanByUserId(userId: Long): VideoSeatBean? {
        return mViews.firstOrNull { it.getData().userBasicVo?.userId == userId }?.getData()

    }

    /**
     * 获取自己座位信息
     */
    fun getMeSeatBean(): VideoSeatBean? {
        return meSeat?.getData()
    }

    /**
     * 获取所有座位的用户信息
     */
    fun getSeatData(): MutableList<VideoSeatBean> {
        val list = mutableListOf<VideoSeatBean>()
        mViews.forEach {
            list.add(it.getData())
        }
        return list
    }

    /**
     * 获取一个无人的麦位
     */
    fun getNoHavaSeat(): VideoSeatBean? {
        return mViews.firstOrNull { it.getData().userBasicVo == null }?.getData()
    }

    /**
     * 更新单个座位数据
     */
    fun setUpdateDateSeat(seatId: Int, mLiveInfo: LiveRoomInfo) {
        mViews[seatId].setData(mLiveInfo)
        checkZegoStream()
    }

    /**
     * 设置加入时的麦位数据全部,初始化
     */
    fun setInitJoinData(mLiveInfo: LiveRoomInfo) {
        mIsInit = true
        //加入时添加监听
        mPartyVideoStreamProxy.setJoinRoom(mVideoStreamManageListener)
        mViews.forEach {
            it.setData(mLiveInfo)
        }
        checkZegoStream()
    }

    /**
     * 检查麦上用户 推拉流
     */
    fun checkZegoStream() {
        if (mIsOnPause) {
            return
        }
        var inSeat = false //自己在座位吗
        mViews.forEachIndexed { _, seatItemView ->
            val seatBean = seatItemView.getData()
            handStream(seatItemView)
            if (seatBean.userBasicVo?.userId == UserManager.getUserId()) {
                inSeat = true
                val nowMicStatus = seatBean.siteMicStatus
                val nowVideoStatus = seatBean.siteVideoStatus
                if (!mLastOnSeatState || mLastSiteMicStatus != nowMicStatus || mLastSiteVideoStatus != nowVideoStatus) {
                    mLastSiteMicStatus = nowMicStatus
                    mLastSiteVideoStatus = nowVideoStatus
                    mPartyVideoSeatListener?.updateOneSelfSeat(seatBean)
                }
                PartyUserStateUtil.siteMicStatus = nowMicStatus
                mLastOnSeatState = true
                meSeat = seatItemView
                PartyUserStateUtil.inTheMaiSeat = true
            }
        }
        if (!inSeat) { //自己没上麦
            if (mLastOnSeatState) {
                mLastOnSeatState = false
                mPartyVideoSeatListener?.updateOneSelfSeat(null)
            }
            mLastSiteMicStatus = null
            mLastSiteVideoStatus = null
            meSeat = null
            PartyUserStateUtil.inTheMaiSeat = false
            PartyUserStateUtil.siteMicStatus = null
            stopPlishStream()
        } else {
            meSeat?.let {
                if (it.getData().siteMicStatus != 1 && it.getData().siteVideoStatus != 1) { //视频和声音都没开启。停止推流
                    stopPlishStream()
                } else {
                    it.getData().siteStreamId?.let { siteStreamId ->
                        publishStream(
                            siteStreamId,
                            it.getData().siteMicStatus == 1,
                            it.getData().siteVideoStatus == 1,
                            it.getTextureView()
                        )
                    }
                }
            }
        }

    }

    /**
     * 判断是否需要拉流
     */
    private fun handStream(seatItemView: T) {
        val seatBean = seatItemView.getData()
        if (seatBean.userBasicVo == null || //没人不拉流
            seatBean.siteStreamId == null ||//没有流Id
            seatBean.siteLock == true || //被锁不拉流
            (seatBean.siteMicStatus != 1 && seatBean.siteVideoStatus != 1)   //关闭了麦克风
        ) {
            mPartyVideoStreamProxy.closeStreamsBySeatId(seatItemView.getSeatId())
            return
        }
        if (seatBean.userBasicVo?.userId == UserManager.getUserId()) {//自己不拉流
            mPartyVideoStreamProxy.closeStreamsBySeatId(seatItemView.getSeatId())
            return
        }
        seatBean.siteStreamId?.let {//有流Id
            mPartyVideoStreamProxy.openStream(seatItemView.getSeatId(), it, seatItemView.getTextureView())
        }
    }

    /**
     * 更新音浪，流等
     */
    private val mVideoStreamManageListener = object : VideoStreamManageListener {
        override fun onCapturedSoundLevelUpdate(soundLevel: Float) {
            meSeat?.soundLevelUpdate(soundLevel)
        }

        override fun onRemoteSoundLevelUpdate(seatId: Int, soundLevel: Float) {
            mViews[seatId].soundLevelUpdate(soundLevel)
        }

    }

    /**
     * 修改派对房用户职位
     */
    fun upDataUserPosition(data: List<Long>) {
        //转成set提高查找效率
        val userIds = data.toSet()
        for (user in mViews) {
            if (userIds.contains(user.getData().userBasicVo?.userId)) {
                user.upDataUserPosition(SeatItemView.ADMINISTRATOR)
            } else {
                user.upDataUserPosition(SeatItemView.GENERAL_AUDIENCE)
            }
        }
    }

    fun onSwitchCamera() {
        mPartyVideoStreamProxy.onSwitchCamera()

    }

    fun getIsOpenCamera(): Boolean {
        return mPartyVideoStreamProxy.getIsOpenCamera()
    }

    /**
     * 展示emoji
     */
    fun showUserEmoji(message: SendLiveMessage) {
        val payload = message.payload as PartyEmojiPayloadBean
        val view = mViews.getOrNull(payload.site) ?: return
        if (view.getData().userBasicVo?.userId == payload.userId) {
            view.showEmoji(message)
        }
    }

    fun setPartySeatListener(listener: PartyVideoSeatListener) {
        mPartyVideoSeatListener = listener
    }

    /**
     * 推流
     */
    private fun publishStream(siteStreamId: String, audio: Boolean, video: Boolean, publishView: TextureView) {
        mPartyVideoStreamProxy.publishStream(siteStreamId, audio, video, publishView)
    }

    /**
     * 停止推流
     */
    fun stopPlishStream() {
        mPartyVideoStreamProxy.stopPublishStream()
    }

    fun onResume() {
        mIsOnPause = false
    }

    fun onPause() {
        mIsOnPause = true
        stopPlishStream()
        mPartyVideoStreamProxy.clearStreams()
    }

    /**
     * 释放
     */
    fun destroyView() {
        mIsInit = false
        mPartyVideoStreamProxy.destroyStreams()

    }

    /**
     * 重置
     */
    fun reset() {
        PartyUserStateUtil.inTheMaiSeat = false
        mIsInit = false
        meSeat = null
        mPartyVideoStreamProxy.destroyStreams()
        mViews.forEach {
            it.resetView()
        }
    }
}